//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

#ifndef __ELASTOS_BSP_MMU_H__
#define __ELASTOS_BSP_MMU_H__

#define KERNEL_PHYSBASE             ((physaddr_t)0xc0000000)
#define KERNEL_IMAGEPHYSBASE        ((physaddr_t)0xc0010000)
#define KERNEL_MEMMAPPEDIOBASE      ((physaddr_t)0x80000000)
#define KERNEL_MEMMAPPEDIOLIMIT     ((physaddr_t)0xa0000000)

#define PHYSADDR(va) \
    ((physaddr_t)(va) - (offset_t)krn.vaKernelVirtBase + \
     (offset_t)KERNEL_PHYSBASE)

#define VIRTADDR(pa) \
    ((virtaddr_t)((pa) - KERNEL_PHYSBASE + (offset_t)krn.vaKernelVirtBase))

// in virtual address
#define PAGE_SHIFT                  (12)
#define PAGEDIR_SHIFT               (20)

#define PAGE_SIZE                   (1u << PAGE_SHIFT)

#define NUMBEROF_PAGES(size)        ((size) >> PAGE_SHIFT)
#define PHYSADDR_TO_PAGENO(pa)      ((pa) >> PAGE_SHIFT)
#define VIRTADDR_TO_PAGENO(va)      PHYSADDR_TO_PAGENO(PHYSADDR(va))
#define PAGENO_TO_PHYSADDR(no)      ((no) << PAGE_SHIFT)
#define PAGENO_TO_VIRTADDR(no)      VIRTADDR(PAGENO_TO_PHYSADDR(no))

const uint_t c_uMaxNumberOfPages    = NUMBEROF_PAGES(0xffffffff) + 1;

const uint_t c_uKernelBasePageNo    =
        PHYSADDR_TO_PAGENO((physaddr_t)krn.vaKernelVirtBase);

const uint_t c_uNumberOfKernelPages =
        c_uMaxNumberOfPages - c_uKernelBasePageNo;

INLINE void FlushCache()
{
    ASM("mov    r1, #3 << 5;"               // 4 segments
        "1:"
        "orr    r2, r1, #63 << 26;"         // 64 entries
        "2:"
        "mcr    p15, 0, r2, c7, c14, 2;"    // clean & invalidate D index
        "subs   r2, r2, #1 << 26;"
        "bcs    2b;"                        // entries 63 to 0
        "subs   r1, r1, #1 << 5;"
        "bcs    1b;"                        // segments 3 to 0
        "mov    r0, #0;"
        "mcr    p15, 0, r0, c7, c10, 4;"    // drain write buffer
        "mcr    p15, 0, r0, c7, c5, 0;"     // BUG: need invalidate I cache?
        : : :"r0", "r1", "r2");
}

INLINE void DisableMMU()
{
    FlushCache();

    ASM("mcr    p15, 0, %0, c1, c0, 0;"
        "nop;"
        "nop;"
        : :"r"(0));
}

#endif //__ELASTOS_BSP_MMU_H__
